package ca.cbc.msb.guice;

import java.util.ArrayList;
import java.util.List;

import javax.jms.JMSException;
import javax.naming.NamingException;

import ca.cbc.msb.mediacms.ChangedMediaNotificationHandler;
import ca.cbc.msb.mediacms.DeletedReleaseNotificationHandler;
import ca.cbc.msb.mediacms.NewReleaseNotificationHandler;
import ca.cbc.msb.mediacms.NotificationHandler;
import ca.cbc.msb.mediacms.NotificationListener;
import ca.cbc.msb.mq.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ca.cbc.msb.daemon.Main;
import ca.cbc.msb.enums.QueueEnum;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;

/**
 * @author Arash Bizhanzadeh <arash.bizhan-zadeh@cbc.ca>
 *         Date: 28/01/11
 *         Time: 3:40 PM
 *         Copyrighted to CBC. All rights reserved.
 */
public class MSBModule extends AbstractModule{

    private static Logger logger = LoggerFactory.getLogger(MSBModule.class);

    TypeLiteral<List<MSBMessageConsumer>> tl = new TypeLiteral<List<MSBMessageConsumer>>(){};

    @Provides @Named("NewReleaseNotificationListener")  @Singleton
    public NotificationListener getNewReleaseNotificationListener(){
        NotificationHandler newRelease = new NewReleaseNotificationHandler();
        return new NotificationListener(newRelease);
    }

    @Provides @Named("DeleteReleaseNotificationListener")
    public NotificationListener getDeleteReleaseNotificationListener(){
        NotificationHandler deleteRelease = new DeletedReleaseNotificationHandler();
        return new NotificationListener(deleteRelease);
    }

    @Provides @Named("ChangeMediaNotificationListener")
    public NotificationListener getChangeMediaNotificationListener(){
        NotificationHandler changeMedia = new ChangedMediaNotificationHandler();
        return new NotificationListener(changeMedia);
    }

    @Provides @Named("ReleaseNotificationQueueConsumer")  @Singleton
    public List<MSBMessageConsumer> getReleaseNotificationQueueConsumer(){
        return createConsumers(QueueEnum.ReleaseNotificationQueue);
    }

    @Provides @Named("DeleteNotificationQueueConsumer")  @Singleton
    public List<MSBMessageConsumer> getDeleteNotificationQueueConsumer(){
        return createConsumers(QueueEnum.DeleteNotificationQueue);
    }

    @Provides @Named("ChangeNotificationQueueConsumer")  @Singleton
    public List<MSBMessageConsumer> getChangeNotificationQueueConsumer(){
        return createConsumers(QueueEnum.ChangeNotificationQueue);
    }
    @Provides @Named("ChangeMediaQueueConsumer")  @Singleton
    public List<MSBMessageConsumer> getChangeMediaQueueConsumer(){
        return createConsumers(QueueEnum.ChangeMediaQueue);
    }

    @Provides @Named("NewReleaseQueueConsumer")  @Singleton
    public List<MSBMessageConsumer> getNewReleaseQueueConsumer(){
        return createConsumers(QueueEnum.NewReleaseQueue);
    }

    @Provides @Named("DeleteReleaseQueueConsumer") @Singleton
    public List<MSBMessageConsumer> getDeleteReleaseQueueConsumer(){
            return createConsumers(QueueEnum.DeleteReleaseQueue);
    }

    @Provides @Named("VerificationQueueConsumer") @Singleton
    public List<MSBMessageConsumer> getVerificationQueueConsumer(){
            return createConsumers(QueueEnum.YospaceVerificationQueue);
    }

    @Provides @Named("FailedVerificationQueueConsumer") @Singleton
    public List<MSBMessageConsumer> getFailedVerificationQueueConsumer(){
        return createConsumers(QueueEnum.YospaceFailed);
    }

     @Provides @Named("GeneralFailedConsumer") @Singleton
    public List<MSBMessageConsumer> getChangeNotificationFailedConsumer(){
        return createConsumers(QueueEnum.GeneralFailed);
    }

    @Override
    protected void configure() {
        bind(Main.class).in(Singleton.class);
        bind(MessageUtil.class).to(MessageUtilImpl.class);
        bind(MSBMessageConsumer.class).to(MessageConsumerImpl.class);
    }

      private List<MSBMessageConsumer> createConsumers( QueueEnum queue) {
        int numberOfThreads = queue.getCount();
        List<MSBMessageConsumer> consumers = new ArrayList<MSBMessageConsumer>();
        try {
                for (int i=0;i<numberOfThreads;i++){
                	MSBMessageConsumer consumer=new MessageConsumerImpl(queue);
                	consumer.setHandler(createHandler(queue));
                    consumers.add(consumer);
                    logger.debug("==============  consumer created: "+queue);
                }
            } catch (NamingException e) {
                logger.error("Error in creating message consumers, JNDI could not be found", e);

            } catch (JMSException e) {
                logger.error("Error in creating message consumers", e);
            }
        return consumers;
    }
      
      
  	private MessageHandler createHandler(QueueEnum queueName) throws NamingException, JMSException{
  		MessageHandler handler=null;
  		switch(queueName){
		case NewReleaseQueue:
			handler = new NewReleaseMessageHandler();
			break;
			
		case DeleteReleaseQueue:
			handler = new DeletedReleaseMessageHandler();
			break;
		
		case ChangeMediaQueue: 
			handler = new ChangedMediaMessageHandler();
			break;
			
		case ChangeNotificationQueue:
		case DeleteNotificationQueue:
		case ReleaseNotificationQueue:
			handler = new NotificationMessageHandler();
			break;
			
		case YospaceVerificationQueue:
			handler = new VideoVerificationMessageHandler();
			break;
        case YospaceFailed:
            handler = new VerificationFailedMessageHandler();
            break;
        case GeneralFailed:
            handler = new GeneralNotificationFailedMessageHandler();
            break;


		default:
			throw new RuntimeException("Unknown Queue " + queueName.name() + " something is terribly wrong");
			
		}
  		return handler;
	}
}
